package com.tantinevincent.parser;

import com.tantinevincent.parser.dynamic_length.ReferenceLength;
import com.tantinevincent.vector.DynamicSparseVector;
import com.tantinevincent.vector.LabeledVector;
import com.tantinevincent.vector.SparseVector;

/**
 * Parser Libsvm format, like: label index:value index:value .....
 * @author Vincent
 *
 */
public class LibsvmParser implements IParser{
	/**
	 * the max length of vector.
	 */
	private ReferenceLength refLength = new ReferenceLength(0);
	
	/**
	 * {@inheritDoc}
	 */
	public LabeledVector parse(String line){
		DynamicSparseVector sv = new DynamicSparseVector(refLength);
		String[] tokens = line.split(" ");
		
		int label = Integer.MAX_VALUE;
		try{
			label = Integer.parseInt(tokens[0]); //split out first toekn
		}catch(Exception ex){
			throwLibsvmFormatErrorException();
		}
		setValueToVector(sv,tokens);
		LabeledVector lv = new LabeledVector(sv,label);
		return lv;
	}
	/**
	 * set every value to vector.
	 * @param sv the vector of raw data
	 * @param tokens the tokens which split by "space".
	 */
	private void setValueToVector(DynamicSparseVector sv,String[] tokens){
		
		for( int i=1; i<=tokens.length-1; i++ ){  // first index is label.
			String[] pair = tokens[i].split(":");  // = index:value
			if( pair.length != 2 ){
				throwLibsvmFormatErrorException();
			}
			int index = Integer.parseInt(pair[0]);			
			if( index > refLength.getLength()-1 ){    // if length need reset because of more longer vector
				refLength.setLength(index+1);
			}
			double value = Double.parseDouble(pair[1]);
			sv.set(index-1, value);  // the libsvm's index start from 1,so need to sub one.
		}
	}
	/**
	 * Throw the data is not Libsvm format. That's it.
	 */
	private void throwLibsvmFormatErrorException(){
		try{
			new Exception("Libsvm format error. Please check the file.");
		}catch( Exception ex ){
			ex.printStackTrace();
			System.exit(-1);
		}
	}
	@Override
	public String toString(){
		return "Libsvm Parser";
	}
}
